import fs from 'node:fs';
import path from 'node:path';
import { __path } from './path';
import { BrowserWindow } from 'electron';
import { fileAlreadyExistDialog, errorDialog } from '../dialog';
import { FileOperationResult, FileExistsOperation, FileWriteResult } from '@type/file';

type ReadFileCallback = (err: NodeJS.ErrnoException | null, data: string | Buffer) => void;
type ReadFileResult<T> = { err: NodeJS.ErrnoException | Error | null; data: T };

// 重载
export function readFile(filePath: string): Promise<ReadFileResult<Buffer>>;
export function readFile(filePath: string, encoding: BufferEncoding): Promise<ReadFileResult<string>>;

/**
 * 读取文件
 */
export function readFile(filePath: string, encoding?: BufferEncoding) {
	return new Promise<ReadFileResult<string | Buffer>>((resolve) => {
		// 文件不存在
		if (!fs.existsSync(filePath)) {
			errorDialog('错误', `读取的文件不存在：${filePath}`);

			return resolve({
				err: new Error('file not exist'),
				data: '',
			});
		}

		// 读取文件回调
		const callback: ReadFileCallback = (err, data) => {
			if (err) {
				return resolve({
					err,
					data: '',
				});
			} else {
				return resolve({
					err: null,
					data,
				});
			}
		};

		if (encoding) {
			fs.readFile(filePath, encoding, callback);
		} else {
			fs.readFile(filePath, callback);
		}
	});
}

/**
 * 写入文件
 */

export function writeFile(filePath: string, data: string | Buffer, encoding?: BufferEncoding) {
	return new Promise<FileWriteResult>((resolve) => {
		const result: FileWriteResult = {
			success: true,
		};

		if (!fs.existsSync(filePath)) {
			const msg = '文件不存在: ' + filePath;

			errorDialog('错误', msg);

			result.success = false;
			result.error = msg;

			resolve(result);
		}

		// 文件写入回调
		const callback: fs.NoParamCallback = (err) => {
			if (err) {
				result.success = false;
				result.error = err.message;
				errorDialog('错误', '文件写入失败: ' + err.message);
			}

			resolve(result);
		};

		// 写入文件
		if (encoding) {
			fs.writeFile(filePath, data, encoding, callback);
		} else {
			fs.writeFile(filePath, data, callback);
		}
	});
}

// 文件存在时操作
async function fileExists(
	result: FileOperationResult,
	win: BrowserWindow | undefined,
	filePath: string,
	fileExistsOperation?: FileExistsOperation
): Promise<{ _continue: boolean; _filePath: string }> {
	let _continue = true;

	// 添加序号方法
	const addNumberFn = () => {
		const newFilePath = __path.addNumber(filePath, 'file');

		if (newFilePath) {
			// 更改文件写入路径，并往结果中加入新的文件路径
			filePath = newFilePath;
			result.newFilePath = newFilePath;
			result.newFilename = path.basename(newFilePath);
		} else {
			// 没有添加成功处理
			result.success = false;
			result.error = 'addNumber Error';

			_continue = false;
		}
	};

	// 是否传入了文件存在时操作参数
	if (!fileExistsOperation) {
		const result1 = await fileAlreadyExistDialog(win, path.basename(filePath), filePath);

		result.rememberMyChoice = result1.learn;
		fileExistsOperation = result1.response;
	}

	result.fileExistsOperation = fileExistsOperation;
	result.type = fileExistsOperation;

	switch (fileExistsOperation) {
		case 'cancel': // 用户选择了取消
			result.success = false;
			_continue = false;
			break;
		case 'addNumber': // 用户选择了添加序号
			addNumberFn();
			break;
		case 'cover': /// 用户选择覆盖
			break;
	}

	return { _continue, _filePath: filePath };
}

/**
 * 写入新文件
 */
export function writeNewFile(
	win: BrowserWindow | undefined,
	filePath: string,
	data: string | Buffer,
	encoding?: BufferEncoding,
	fileExistsOperation?: FileExistsOperation
) {
	return new Promise<FileOperationResult>(async (resolve) => {
		let runWrite = true; // 是否运行写入
		// 返回结果
		const result: FileOperationResult = {
			success: true,
			type: 'success',
		};

		// 文件写入回调
		const callback: fs.NoParamCallback = (err) => {
			if (err) {
				result.success = false;
				result.error = err.message;
			}

			resolve(result);
		};

		// 文件存在时操作
		if (fs.existsSync(filePath)) {
			const { _continue, _filePath } = await fileExists(result, win, filePath, fileExistsOperation);

			filePath = _filePath;
			runWrite = _continue;
		}

		if (runWrite) {
			// 写入文件
			if (encoding) {
				fs.writeFile(filePath, data, encoding, callback);
			} else {
				fs.writeFile(filePath, data, callback);
			}
		} else {
			resolve(result);
		}
	});
}

/**
 * 复制文件
 */
export function copyFile(
	win: BrowserWindow | undefined,
	src: string,
	dest: string,
	fileExistsOperation?: FileExistsOperation
) {
	return new Promise<FileOperationResult>(async (resolve) => {
		let runCopy = true;
		const result: FileOperationResult = {
			success: true,
			type: 'success',
		};

		// 文件存在时操作
		if (fs.existsSync(dest)) {
			const { _continue, _filePath } = await fileExists(result, win, dest, fileExistsOperation);

			dest = _filePath;
			runCopy = _continue;
		}

		if (runCopy) {
			fs.copyFile(src, dest, (err) => {
				if (err) {
					result.success = false;
					result.error = err.message;
				}

				resolve(result);
			});
		} else {
			resolve(result);
		}
	});
}

/**
 * 移动文件
 */
export function moveFile(
	win: BrowserWindow | undefined,
	oldPath: string,
	newPath: string,
	fileExistsOperation?: FileExistsOperation
) {
	return new Promise<FileOperationResult>(async (resolve) => {
		let runMove = true;
		const result: FileOperationResult = {
			success: true,
			type: 'success',
		};

		// 文件存在时操作
		if (fs.existsSync(newPath)) {
			const { _continue, _filePath } = await fileExists(result, win, newPath, fileExistsOperation);

			newPath = _filePath;
			runMove = _continue;
		}

		if (runMove) {
			fs.rename(oldPath, newPath, (err) => {
				if (err) {
					result.success = false;
					result.error = err.message;
				}
				resolve(result);
			});
		}
	});
}

/**
 * 创建文件夹
 */
export function mkdir(_path: string, recursive = false) {
	return new Promise<string>((resolve, reject) => {
		fs.mkdir(
			_path,
			{
				recursive,
			},
			(err, _path_) => {
				if (err) {
					errorDialog('错误', `创建目录失败：${_path}`);
					reject(err);
				} else {
					resolve(_path_ as string);
				}
			}
		);
	});
}
